Propagate Composable requirement to implementors of lambda interfaces. Propagates requirement of composable invoke operator override to classes and interfaces that are extending lambda interfaces with corresponding annotations. Test: ComposableDeclarationCheckerTests Change-Id: Id2757562f10a2f0da198c7cce602d8ea8726b809 
diff --git a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableDeclarationCheckerTests.kt b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableDeclarationCheckerTests.kt index 3239060..07aa897 100644 --- a/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableDeclarationCheckerTests.kt +++ b/compose/compiler/compiler-hosted/integration-tests/src/test/java/androidx/compose/compiler/plugins/kotlin/analysis/ComposableDeclarationCheckerTests.kt 
@@ -286,4 +286,74 @@  """  )  } + + @Test + fun testOverrideComposableLambda() { + check( + """ + import androidx.compose.runtime.Composable + + class Impl : @Composable () -> Unit { + @Composable + override fun invoke() {} + } + """ + ) + } + + @Test + fun testTransitiveOverrideComposableLambda() { + check( + """ + import androidx.compose.runtime.Composable + + interface ComposableFunction : @Composable () -> Unit + + class Impl : ComposableFunction { + @Composable + override fun invoke() {} + } + """ + ) + } + + @Test + fun testMissingOverrideComposableLambda() { + check( + """ + import androidx.compose.runtime.Composable + + class Impl : @Composable () -> Unit { + <!CONFLICTING_OVERLOADS!>override fun invoke()<!> {} + } + """ + ) + } + + @Test + fun testWrongOverrideLambda() { + check( + """ + import androidx.compose.runtime.Composable + + class Impl : () -> Unit { + <!CONFLICTING_OVERLOADS!>@Composable override fun invoke()<!> {} + } + """ + ) + } + + @Test + fun testMultipleOverrideLambda() { + check( + """ + import androidx.compose.runtime.Composable + + class Impl : () -> Unit, @Composable (Int) -> Unit { + <!CONFLICTING_OVERLOADS!>@Composable override fun invoke()<!> {} + @Composable override fun invoke(p0: Int) {} + } + """ + ) + }  } 
diff --git a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableDeclarationChecker.kt b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableDeclarationChecker.kt index c0aad2e..2cc17dc 100644 --- a/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableDeclarationChecker.kt +++ b/compose/compiler/compiler-hosted/src/main/java/androidx/compose/compiler/plugins/kotlin/ComposableDeclarationChecker.kt 
@@ -22,9 +22,11 @@  import androidx.compose.compiler.plugins.kotlin.ComposeErrors.COMPOSABLE_SUSPEND_FUN  import androidx.compose.compiler.plugins.kotlin.ComposeErrors.COMPOSABLE_VAR  import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.builtins.isFunctionType  import org.jetbrains.kotlin.builtins.isSuspendFunctionType  import org.jetbrains.kotlin.container.StorageComponentContainer  import org.jetbrains.kotlin.container.useInstance +import org.jetbrains.kotlin.descriptors.ClassDescriptor  import org.jetbrains.kotlin.descriptors.DeclarationDescriptor  import org.jetbrains.kotlin.descriptors.FunctionDescriptor  import org.jetbrains.kotlin.descriptors.Modality @@ -41,6 +43,7 @@  import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker  import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext  import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.typeUtil.supertypes  import org.jetbrains.kotlin.util.OperatorNameConventions    class ComposableDeclarationChecker : DeclarationChecker, StorageComponentContainerContributor { @@ -79,7 +82,22 @@  val hasComposableAnnotation = descriptor.hasComposableAnnotation()  if (descriptor.overriddenDescriptors.isNotEmpty()) {  val override = descriptor.overriddenDescriptors.first() - if (override.hasComposableAnnotation() != hasComposableAnnotation) { + val overrideFunctionIsComposable = + if (descriptor.isOperator && descriptor.name == OperatorNameConventions.INVOKE) { + override.hasComposableAnnotation() || descriptor.let { + val cls = descriptor.containingDeclaration as? ClassDescriptor + cls?.run { + defaultType.supertypes().any { + it.isFunctionType && + it.arguments.size == descriptor.arity + 1 && + it.hasComposableAnnotation() + } + } ?: false + } + } else { + override.hasComposableAnnotation() + } + if (overrideFunctionIsComposable != hasComposableAnnotation) {  context.trace.report(  ComposeErrors.CONFLICTING_OVERLOADS.on(  declaration, @@ -234,4 +252,9 @@  context.trace.report(COMPOSABLE_VAR.on(name))  }  } + + private val FunctionDescriptor.arity get(): Int = + if (extensionReceiverParameter != null) 1 else 0 + + contextReceiverParameters.size + + valueParameters.size  }